<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

/**
 * 兑换码活动管理控制器
 * 用于管理后台的兑换码活动和兑换码生成
 */
class CodeController extends Controller
{
    /**
     * 允许使用的字符集
     * 不包含容易混淆的字符：0,1,I,L,O
     */
    private $allowedNumbers = ['2', '3', '4', '5', '6', '7', '8', '9'];
    private $allowedLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

    /**
     * 生成唯一的兑换码
     * 规则：12位字符，包含数字和大写字母，排除易混淆字符
     *
     * @return string
     * @throws \RuntimeException 当无法生成唯一兑换码时抛出异常
     */
    private function generateUniqueCode()
    {
        $characters = array_merge($this->allowedNumbers, $this->allowedLetters);
        $maxAttempts = 10; // 最大尝试次数
        $attempt = 0;

        do {
            $code = '';
            // 确保至少包含一个数字和一个字母
            $code .= $this->allowedNumbers[array_rand($this->allowedNumbers)]; // 保证第一位是数字
            $code .= $this->allowedLetters[array_rand($this->allowedLetters)]; // 保证第二位是字母
            
            // 生成剩余10位
            for ($i = 0; $i < 10; $i++) {
                $code .= $characters[array_rand($characters)];
            }

            // 打乱字符顺序
            $codeArray = str_split($code);
            shuffle($codeArray);
            $code = implode('', $codeArray);

            // 检查数据库中是否已存在
            $exists = \App\Models\RedemptionCode::where('code', $code)->exists();
            
            $attempt++;
            
            // 如果尝试次数过多，调整生成策略
            if ($attempt >= $maxAttempts) {
                // 添加时间戳信息来增加唯一性
                $timestamp = substr(time(), -2);
                $code = substr($code, 0, 10) . $timestamp;
            }
        } while ($exists && $attempt < $maxAttempts * 2);

        if ($exists) {
            throw new \RuntimeException('无法生成唯一的兑换码，请稍后重试');
        }

        return $code;
    }

    /**
     * 显示兑换活动列表页面
     *
     * @param Request $request
     * @return \Illuminate\View\View
     */
    public function index(Request $request)
    {
        // 获取类型参数
        $type = $request->query('type', 'time_access'); // 默认显示time_access类型
        
        // 构建查询，从redemption_codes表中获取数据
        $query = \App\Models\RedemptionCode::query();
        
        // 根据类型参数过滤
        $query->where('type', $type);
        
        // 获取分页数据
        $redemptionCodes = $query->latest()->paginate(15);
        
        // 获取商品列表，用于商品兑换码
        $products = Product::select(['id', 'name', 'price'])
            ->get();
            
        $hasProducts = $products->isNotEmpty();  // 检查是否有商品
            
        // 传递类型参数到视图
        return view('codes.index', compact('redemptionCodes', 'products', 'hasProducts', 'type'));
    }

    /**
     * 创建新的兑换码
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        try {
            // 获取类型参数
            $type = $request->query('type', 'time_access');
            
            // 定义验证规则，根据类型有所不同
            $rules = [
                'name' => 'required|string|max:255',
                'total_codes' => 'required|integer|min:1|max:1000',
            ];
            
            // 根据类型添加特定的验证规则
            if ($type == 'time_access') {
                $rules['value'] = 'required|integer|min:1';
            } elseif ($type == 'product_exchange') {
                $rules['product_id'] = 'required|exists:products,id';
                $rules['value'] = 'required|numeric|min:0';
            } elseif ($type == 'discount') {
                $rules['value'] = 'required|numeric|min:0';
            }
            
            // 验证请求数据
            $validated = $request->validate($rules);
            
            // 设置过期时间，如果未设置则使用默认值（5年后）
            $expiredAt = $request->end_time ? 
                Carbon::parse($request->end_time)->format('Y-m-d H:i:s') : 
                Carbon::now()->addYears(2)->format('Y-m-d H:i:s');  //生成2年后的日期
            
            // 准备批量插入的数据
            $redemptionCodes = [];
            $totalCodes = $request->total_codes;
            
            // 生成兑换码
            for ($i = 0; $i < $totalCodes; $i++) {
                // 生成唯一的兑换码
                $code = $this->generateUniqueCode();
                
                // 根据类型设置不同的metadata
                $metadata = [];
                switch ($type) {
                    case 'time_access':
                        // 会费兑换码，设置天数和权限等级
                        $metadata = [
                            'days' => $request->value,
                            'permission_level' => 'basic' // 默认为basic
                        ];
                        break;
                    case 'product_exchange':
                        // 商品兑换码
                        $product = Product::find($request->product_id);
                        $metadata = [
                            'product_id' => $request->product_id,
                            'product_name' => $product ? $product->name : '',
                            'quantity' => 1
                        ];
                        break;
                    case 'discount':
                        // 折扣兑换码
                        $metadata = [
                            'amount' => $request->value,
                            'currency' => 'CNY'
                        ];
                        break;
                }
                
                $redemptionCodes[] = [
                    'code' => $code,
                    'name' => $request->name,
                    'type' => $type,
                    'status' => 'unused',
                    'expired_at' => $expiredAt,
                    'metadata' => json_encode($metadata),
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
            
            // 批量插入兑换码
            foreach (array_chunk($redemptionCodes, 100) as $chunk) {
                \App\Models\RedemptionCode::insert($chunk);
            }
            
            // 显示成功消息
            return redirect()->route('codes.index', ['type' => $type])
                ->with('success', '兑换码创建成功，共生成' . $totalCodes . '个兑换码。');
            
        } catch (\Exception $e) {
            // 记录错误日志
            Log::error('创建兑换码失败: ' . $e->getMessage());
            
            // 显示错误消息
            return redirect()->back()
                ->with('error', '创建兑换码失败，请稍后重试。')
                ->withInput();
        }
    }

    /**
     * 生成单个兑换码的二维码
     *
     * @param string $code 兑换码
     * @return \Illuminate\Http\Response
     */
    public function generateQrCode($code)
    {
        try {
            // 生成二维码内容，包含兑换码作为参数
            $qrContent = route('wechat.service.account.redeem') . '?code=' . $code;
            
            // 生成二维码图片，使用PNG格式
            $qrCode = QrCode::format('png')->size(300)->margin(2)->generate($qrContent);
            
            // 返回PNG响应
            return response($qrCode)
                ->header('Content-Type', 'image/png')
                ->header('Content-Disposition', 'attachment; filename="redeem_qr_' . $code . '.png"');
        } catch (\Exception $e) {
            \Log::error('生成二维码失败: ' . $e->getMessage());
            return redirect()->back()->with('error', '生成二维码失败');
        }
    }

    /**
     * 生成并下载兑换码二维码
     *
     * @param int $id 兑换码ID
     * @return \Illuminate\Http\Response
     */
    public function downloadQrCode($id)
    {
        try {
            // 查找兑换码
            $redemptionCode = \App\Models\RedemptionCode::findOrFail($id);
            
            // 生成二维码内容，包含兑换码作为参数
            $qrContent = route('wechat.service.account.redeem') . '?code=' . $redemptionCode->code;
            
            // 生成二维码图片，使用PNG格式
            $qrCode = QrCode::format('png')->size(300)->margin(2)->generate($qrContent);
            
            // 返回PNG响应
            return response($qrCode)
                ->header('Content-Type', 'image/png')
                ->header('Content-Disposition', 'attachment; filename="redeem_qr_' . $redemptionCode->code . '.png"');
        } catch (\Exception $e) {
            \Log::error('生成二维码失败: ' . $e->getMessage());
            return redirect()->back()->with('error', '生成二维码失败: ' . $e->getMessage());
        }
    }

    /**
     * 根据兑换码搜索
     *
     * @param Request $request
     * @return \Illuminate\View\View
     */
    public function search(Request $request)
    {
        $searchTerm = $request->input('search');
        $type = $request->query('type', 'time_access');
        
        $query = \App\Models\RedemptionCode::query();
        $query->where('type', $type);
        
        // 如果有搜索条件，添加过滤
        if (!empty($searchTerm)) {
            $query->where('code', 'like', "%{$searchTerm}%");
        }
        
        $redemptionCodes = $query->latest()->paginate(15);
        
        // 获取商品列表
        $products = Product::select(['id', 'name', 'price'])->get();
        $hasProducts = $products->isNotEmpty();
        
        return view('codes.index', compact('redemptionCodes', 'products', 'hasProducts', 'type'));
    }
}